kimjeongwonnabout

[CS] 스레드

프로세스 내에서 스레드의 역할

  • Light Weight Process 라고 부르기도 함 → 프로세스 처럼 동작하지만 더 가볍고 작음
  • 프로세스는 기본적으로 직접적으로 데이터 접근이 불가능 → IPC 기법을 활용해 간접적으로 데이터 통신을 사용
  • 스레드는 하나의 프로세스 안에서 생성되며 다수의 스레드 생성 가능
  • 스레드들은 동시에 실행 가능 → 병렬 처리가 가능
  • 하나의 프로세스 안에서 동작하므로 프로세스 내부의 데이터를 공유하며 접근 가능

스레드의 구조

  • 하나의 프로세스 내에서 스택과 레지스터(PC, SP)를 스레드별로 별도로 관리한다.
    • 실제로는 프로세스의 스택과 힙 영역 사이에 공간을 할당한다.
  • 때문에 스택영역 외(힙, 코드, 데이터)에는 하나의 프로세스 내에서 스레드끼리 공유가 가능하다

멀티 태스킹 / 멀티 프로세싱

멀티 태스킹

  • 다수의 프로세스를 하나의 CPU가 빠르게 교체하면서 작업하여 동시에 여러개의 프로세스가 구동되는 것처럼 하는 기능
  • 스케쥴러와 컨텍스트 스위칭을 통해 구현할 수 있음

멀티 프로세싱

  • 하나 혹은 다수의 프로세스를 다수의 코어가 분할하여 작업을 처리하는 방법
  • 하나의 프로세스 내의 다수의 스레드를 각 코어가 병렬로 처리해 하나의 프로세스의 작업을 다수의 코어가 나누어 처리할 수 있음

장단점

장점

  • 프로세스 내에서 기능별로 스레드를 구분하면, 하나의 기능이 지연되어도 프로세스의 응답성을 보장할 수 있음
  • 프로세스 내의 스레드 사이에서 공유되는 영역(코드, 힙, 데이터)에서 IPC처리 없이 직접 자원 공유가 가능
  • 하나의 프로세스 내에서 다수의 스택을 사용하기 때문에 시스템자원을 절약할 수 있음

단점

  • 프로세스 내부의 하나의 스레드에만 문제가 생겨도 전체 프로세스가 영향을 받음
    • 크롬 브라우저에서는 멀티 프로세스를 활용하기 때문에 하나의 탭에 문제가 생겨도 다른 탭에 영향이 없음
  • 스레드를 많이 생성하게 되면 컨텍스트 스위칭이 자주 일어나 성능이 저하될 수 있음 → 리눅스에서는 쓰레드와 프로세스를 같이 다루기 때문에 모두 스케쥴링 하게 됨
  • 프로그램이 복잡해짐

동기화 이슈

  • 다수의 스레드 사이의 실행 순서는 보장되지 않기 때문에 공유된 공간의 변수를 사용할 때 예측하지 못한 동작이 일어날 수 있음
    • 코드가 실행될 때 어셈블리어 레벨의 연산 중간에 컨텍스트 스위칭이 일어나게 되면 연산이 누락되는 등의 문제가 발생할 수 있음
  • 때문에 다양한 방법을 통해 스레드의 작업 순서를 맞춰 동기화에 문제가 없게 해야함

Mutual Exclusion (상호 배제)

  • 스레드에서 하나의 연산을 하나의 스레드가 끝낼 때 까지 다른 스레드에서 접근하지 못하도록 방지하는 기법
  • 하나의 연산을 점유하고 있는 스레드가 중간에 컨텍스트 스위칭이 일어나 다른 스레드에서 같은 연산을 처리할 때 이미 점유중인 스레드가 있다면 해당 스레드는 점유가 끝날 때 까지 대기함
  • 스레드에서 반드시 한 번에 처리되어야 하는 임계영역을 지정하여 임계자원의 동기화를 보장할 수 있음

Mutex와 Semaphore(세마포어)

  • Mutex(Binary Semaphore)
    • 임계구역에 하나의 스레드만 들어갈 수 있음
  • Semaphore
    • 임계구역 내에 다수의 스레드가 들어갈 수 있음
    • Counter를 통해 리소스에 접근할 수 있는 허용 가능한 스레드 수를 제어
    • 바쁜 대기 → 임계구역에 접근하지 못하도록 스레드 내에서 Counter 값을 조건으로 임계구역 앞에서 무한 Loop를 돌려 접근을 방지시킴
    • 대기 큐 → 운영체제 기술로 해당 스레드의 상태를 ready상태에서 대기 상태로 바꾸거나 스케쥴러의 대기 큐에 할당하여 접근을 방지시킴
      • 세마포어를 구현해 놓은 시스템 API 함수가 있음 → POSIX 세마포어
        • sem_open() : 세마포어 생성
        • sem_wait() : 임계영역 접근 전 세마포어 상태를 확인해 세마포어를 잠그거나 풀릴 때 까지 대기
        • sem_post() : 임계영역에 대한 접근이 끝나고 세마포어의 잠금을 해제

Deadlock(교착상태)와 Starvation(기아상태)

교착상태(Deadlock)

  • 무한 대기 상태 : 두 개 이상의 작업이 서로 작업이 끝나야 진행할 수 있는 상태에서 대기하게 되어 진행이 되지 않는 상태
  • 교착 상태가 발생하는 조건 4가지
    • Mutual exclusion (상호 배제) : 프로세스들이 필요로 하는 자원에 대해 배타적인 통제권을 요구
    • Hold and wait (점유 대기) : 프로세스가 할당된 자원을 가진 상태에서 다른 자원을 기다림
    • No preemption (비선점) : 프로세스가 어떤 자원의 사용을 끝내기 전까지 그 자원을 선점할 수 없음
    • Circular wait (순환 대기) : 각 프로세스는 순환적으로 다음 프로세스가 요구하는 자원을 갖고 있음
  • 위의 네가지 조건 중에 하나를 예방/해결하는 방법으로 교착상태를 방지할 수있다

기아상태(Starvation)

  • 특정 프로세스(스레드)의 우선순위가 낮아서 원하는 자원을 계속 할당 받지 못하는 상태
  • 교착상태와 차이 → 교착상태는 여러 프로세스가 동일 자원 점유를 요청할 때 발생, 기아상태는 여러 프로세스가 작원을 점유할 때, 우선순위가 낮은 프로세스가 영원히 자원 할당이 되지 않는 경우를 의미
  • 우선순위를 수시로 변경해서 해결
    • 오래 기다린 프로세스의 우선순위를 높여주기
    • 우선순위가 아니라 Queue방식으로 처리